/**
 * 优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。 
 * 比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。 
 * 程序会打印高于或等于所设置级别的日志，设置的日志等级越高，打印出来的日志就越少。
 */

export default class Logger {

    private log_types = ["debug", "debug", "info", "warn", "error"];

    public Level = {
        //TRACE : 0,
        DEBUG: 1,
        INFO: 2,
        WARN: 3,
        ERROR: 4,
        //_FATAL : 5,
        OFF: 6  //    关闭
    };

    public DEBUG = this.Level.DEBUG;
    public ERROR = this.Level.ERROR;
    public INFO = this.Level.INFO;
    public WARN = this.Level.WARN;
    public OFF = this.Level.OFF;

    //生产环境，关闭日志
    public PROD = this.OFF;

    public sdk: Logger;

    public static logPlain = false;

    private _level: number;

    private env: number;


    constructor() {

    }


    /**
     * 兼容之前版本，此方法无效
     * @param _env 
     */
    setEnv(_env) {
        this._level = this.Level.DEBUG;
    }

    setLevel(_level: number) {
        this._level = _level;
    }

    setLogPlain(plain: boolean) {
        Logger.logPlain = plain;
    }

    /**
     * 默认是debug
     * @param logger 
     * @param msg 
     */
    log(logger: any = null, ...msg: any[]) {
        this.debug(logger, msg);
    }

    private format = function (msg: string, optionalParams: any[]) {
        return msg + " " + optionalParams.map(function (x) {
            if (x !== undefined) {
                switch (typeof x) {
                    case "object":
                        try {
                            return JSON.stringify(x);
                        }
                        catch (error) {
                            return x.toString() + "(" + error + ")";
                        }
                    default:
                        return x.toString();
                }
            }
        }).join(" ");
    }

    private formatX = function (optionalParams: any[]) {
        return optionalParams.map(function (x) {
            if (x !== undefined) {
                switch (typeof x) {
                    case "object":
                        try {
                            return JSON.stringify(x);
                        }
                        catch (error) {
                            return x.toString() + "(" + error + ")";
                        }
                    default:
                        return x.toString();
                }
            }
        });
    }

    private output(level: number, msg: any, optionalParams: any[]) {
        if (level >= this._level) {
            // for global vars console !== undefined throws an error
            if (typeof console !== "undefined" && msg !== undefined) {
                try {
                    var logMethod = console[this.log_types[level]];
                    if (!logMethod) {
                        logMethod = console["log"];
                    }
                    if (logMethod) {
                        if (logMethod.call) {
                            if (Logger.logPlain)
                                logMethod.call(console, this.format(msg, optionalParams));
                            else
                                logMethod.call(console, msg, optionalParams);
                        } else {
                            if (Logger.logPlain)
                                logMethod(console, this.format(msg, optionalParams));
                            else
                                logMethod(console, msg, optionalParams);
                        }
                    }
                }
                catch (error) {
                }
            }
        }
    }

    debug(logger: any = null, ...msg: any[]) {
        if (!!!msg) {
            msg = [logger];
            logger = '';
        }
        this.output(this.Level.DEBUG, logger, msg);
    }


    info(logger: any = null, ...msg: any[]) {
        if (!!!msg) {
            msg = [logger];
            logger = '';
        }
        this.output(this.Level.INFO, logger, msg);
    }

    warn(logger: any = null, ...msg: any[]) {
        if (!!!msg) {
            msg = [logger];
            logger = '';
        }
        this.output(this.Level.WARN, logger, msg);
    }



    error(logger: any = null, ...msg: any[]) {
        if (!!!msg) {
            msg = [logger];
            logger = '';
        }
        this.output(this.Level.ERROR, logger, msg);
    }
}